package com.spring.mqtt;

import com.alibaba.fastjson2.JSONObject;
import com.spring.mqtt.annotation.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.UUID;

@Component
@Slf4j
public class MqttControllerProcessor{
    @Autowired
    MqttUtilsBean mqttUtilsBean;
    @Autowired
    MqttGateway mqtt;


    @SneakyThrows
    public void message(Message<?> message){

        String payload = message.getPayload().toString();
        MessageHeaders messageHeaders = message.getHeaders();
        UUID packetId = messageHeaders.getId();
        Integer qos = (Integer) messageHeaders.get(MqttHeaders.RECEIVED_QOS);
        String recvTopic = (String) messageHeaders.get(MqttHeaders.RECEIVED_TOPIC);
        if (recvTopic==null) return;

        for (Object bean : mqttUtilsBean.getControllerBeans()) {
            Method[] methods = bean.getClass().getDeclaredMethods();
            for (Method method : methods) {

                if (method.isAnnotationPresent(MqttSubscirbe.class)) {
                    method.setAccessible(true);

                    MqttSubscirbe mqttSubscirbe = method.getAnnotation(MqttSubscirbe.class);
                    String originalTopic = mqttSubscirbe.topic();
                    MqttTopicUtils mqttTopicUtils = new MqttTopicUtils(recvTopic,originalTopic);
                    String[] recvLevels = mqttTopicUtils.getRecvTopicLevels();

                    // 匹配topic规则
                    if (!MqttTopic.isMatched(mqttTopicUtils.getSubscribeTopic(),recvTopic)) return;
                    JSONObject data = JSONObject.parseObject(payload);
                    // 数据初始化完毕 开始过滤

                    //获取过滤器Bean
                    Object filterBean = null;
                    for (Object var : mqttUtilsBean.getFilterBeans()) {
                        Class<?> clazz = var.getClass();
                        if (clazz.isAnnotationPresent(MqttFilter.class)) {
                            if (clazz.getAnnotation(MqttFilter.class).value().equals(originalTopic)){
                                filterBean = var;
                            }
                        }


                    }

                    // 执行前方法
                    if (filterBean!=null){
                        Method before = filterBean.getClass().getDeclaredMethod("before", MqttTopicUtils.class, JSONObject.class);
                        before.setAccessible(true);
                        if (!(boolean)before.invoke(filterBean, mqttTopicUtils,data)) return;
                    }

                    if (method.isAnnotationPresent(MqttTopicFilter.class)){
                        MqttTopicFilter mqttTopicFilter = method.getAnnotation(MqttTopicFilter.class);
                        MqttTopicMap[] mqttTopicMaps = mqttTopicFilter.map();
                        for (MqttTopicMap mqttTopicMap : mqttTopicMaps) {
                            String filterKey = mqttTopicMap.key();
                            String filterValue = mqttTopicMap.value();
                            MqttTopicFilterType type = mqttTopicMap.type();
                            for (Map.Entry<String, Object> var : mqttTopicUtils.getRecvTopicMap().entrySet()) {
                                if(filterKey.equals(var.getKey())) {

                                    if(type == MqttTopicFilterType.StartsWith && filterValue.startsWith((String) var.getValue())) {
                                        log.info(originalTopic+" filterMap key:" + filterKey + "   StartsWith value:" + filterValue);
                                        return;
                                    }else if(type == MqttTopicFilterType.EndsWith && filterValue.endsWith((String) var.getValue())) {
                                        log.info(originalTopic+" filterMap key:" + filterKey + "   EndsWith value:" + filterValue);
                                        return;
                                    }else if(type == MqttTopicFilterType.ContentWith && filterValue.contains((String) var.getValue())) {
                                        log.info(originalTopic+" filterMap key:" + filterKey + "   ContentWith value:" + filterValue);
                                        return;
                                    }else if(type == MqttTopicFilterType.All && filterValue.equalsIgnoreCase((String) var.getValue())) {
                                        log.info(originalTopic+" filterMap key:" + filterKey + "   All value:" + filterValue);
                                        return;
                                    }
                                }
                            }
                        }

                        MqttTopicLevel[] filterLevels = mqttTopicFilter.level();
                        for (MqttTopicLevel level : filterLevels) {
                            int filterIndex = level.index();
                            String filterName = level.name();
                            MqttTopicFilterType type = level.type();
                            String filterData = recvLevels[filterIndex];
                                if(type == MqttTopicFilterType.StartsWith && filterData.startsWith(filterName)) {
                                    log.info(originalTopic+" filterMap index:" + filterIndex + "   StartsWith value:" + filterData);
                                    return;
                                }else if(type == MqttTopicFilterType.EndsWith && filterData.endsWith(filterName)) {
                                    log.info(originalTopic+" filterMap index:" + filterIndex + "   EndsWith value:" + filterData);
                                    return;
                                }else if(type == MqttTopicFilterType.ContentWith && filterData.contains(filterName)) {
                                    log.info(originalTopic+" filterMap index:" + filterIndex + "   ContentWith value:" + filterData);
                                    return;
                                }else if(type == MqttTopicFilterType.All && filterData.equals(filterName)) {
                                    log.info(originalTopic+" filterMap index:" + filterIndex + "   All value:" + filterData);
                                    return;
                                }


                        }

                    }
                    //完成过滤 执行方法
                    Object methodRet = method.invoke(bean, mqttTopicUtils,data);
                    if(methodRet != null && methodRet.getClass() == MqttReturn.class){
                            MqttReturn m = (MqttReturn)methodRet;
                            mqtt.send(m.getTopic(), m.getQos(),JSONObject.from(m.getPayload()).toString());
                    }
                    if (filterBean!=null){
                        Method before = filterBean.getClass().getDeclaredMethod("after", MqttTopicUtils.class, JSONObject.class);
                        before.setAccessible(true);
                        if (!(boolean)before.invoke(filterBean, mqttTopicUtils,data)) return;
                    }



                }
            }
        }

    }

    public void MqttMappingFilter(Method method){

    }

}
